package org.amphiprion.montrictracv4.task.ludotheque;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.amphiprion.apiforanywebsite.engine.WebMarshaller;
import org.amphiprion.montrictracv4.ApplicationConstants;
import org.amphiprion.montrictracv4.db.dao.LudothequeDao;
import org.amphiprion.montrictracv4.db.model.Game;
import org.amphiprion.montrictracv4.db.model.Ludotheque;
import org.amphiprion.montrictracv4.db.model.LudothequeGame;
import org.amphiprion.montrictracv4.web.model.Member;
import org.amphiprion.montrictracv4.web.model.WebGame;
import org.amphiprion.montrictracv4.web.model.WebLudotheque;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import android.content.Context;
import android.util.Log;

public class WebLudothequeParser {
	private List<LudothequeGame> links;
	private int gameParsed;
	private int nbGames;
	private Context context;
	private String member;
	private String memberName;
	private SynchronizeLudothequeTask task;
	private Ludotheque existingLudo;

	WebLudothequeParser(Context context, Member oMember, SynchronizeLudothequeTask task, Ludotheque existingLudo) {
		if (oMember != null) {
			int p2 = oMember.mur.lastIndexOf('/');
			int p1 = oMember.mur.lastIndexOf('/', p2 - 1);
			member = oMember.mur.substring(p1 + 1, p2);
			memberName = oMember.name;
		} else {
			member = existingLudo.getId();
			memberName = existingLudo.name;
		}

		this.context = context;
		this.task = task;
		this.existingLudo = existingLudo;
	}

	public List<LudothequeGame> parse() {
		try {
			Ludotheque ludo = null;
			if (existingLudo != null) {
				ludo = existingLudo;
			} else {
				boolean exists = LudothequeDao.getInstance(context).isInDb(member);
				ludo = new Ludotheque(member, !exists);
			}
			links = new ArrayList<LudothequeGame>();
			gameParsed = 0;
			int numPage = 1;
			while (numPage == 1 || gameParsed < nbGames) {
				boolean gamefound = collectPage(ludo, numPage);
				if (task.isCancelled()) {
					return null;
				}
				if (!gamefound) {
					break;
				}
				numPage++;
			}
			ludo.lastSynchro = new Date();
			LudothequeDao.getInstance(context).persist(ludo);
			LudothequeDao.getInstance(context).updateLinks(member, links);
			return links;
		} catch (Throwable e) {
			Log.e(ApplicationConstants.PACKAGE, "", e);
			return null;
		}
	}

	private boolean collectPage(Ludotheque ludo, int numPage) throws Throwable {

		String url = null;
		if (numPage == 1) {
			url = "http://www.trictrac.net/mur/" + member + "/ludotheque";
		} else {
			url = "http://www.trictrac.net/jeu-de-societe/les-jeux-du-membre/" + member + "/my-boardgame-library/list60/" + numPage + "/32";
		}

		boolean succeed = false;
		int nbRetry = 0;
		int maxRetry = 3;
		Exception memE = null;
		Document doc = null;
		while (nbRetry <= maxRetry && !succeed) {
			try {
				doc = Jsoup.connect(url).get();
				succeed = true;
			} catch (Exception eee) {
				nbRetry++;
				memE = eee;
				Log.w(ApplicationConstants.PACKAGE, "Retry " + nbRetry + " due to " + eee.getClass().getName() + ": " + eee.getMessage());
			}
		}
		if (!succeed) {
			throw memE;
		}
		WebMarshaller<WebLudotheque> m = new WebMarshaller<WebLudotheque>(WebLudotheque.class);
		List<WebLudotheque> list = m.marshall(doc);
		if (list.size() > 0) {
			WebLudotheque webLudo = list.get(0);
			if (numPage == 1) {
				nbGames = webLudo.nbGames;
				ludo.count = nbGames;
				ludo.name = memberName;
				if (webLudo.image != null && webLudo.image.startsWith("/")) {
					ludo.image = ApplicationConstants.URL_ROOT + webLudo.image;
				} else {
					ludo.image = webLudo.image;
				}
			}
			if (webLudo.games == null || webLudo.games.size() == 0) {
				return false;
			}
			for (WebGame game : webLudo.games) {
				if (task.isCancelled()) {
					return false;
				}
				collectGame(game);
			}
			return true;
		}
		return false;
	}

	private void collectGame(WebGame webGame) throws Exception {
		gameParsed++;
		task.publishProgress(gameParsed, nbGames);
		String url = webGame.link;
		if (url.startsWith("/")) {
			url = ApplicationConstants.URL_ROOT + url;
		}
		int p2 = url.lastIndexOf('/');
		int p1 = url.lastIndexOf('/', p2 - 1);
		String id = url.substring(p1 + 1, p2);

		Game game = WebGameParser.parse(context, id);
		if (game != null) {
			LudothequeGame lg = new LudothequeGame();
			lg.gameId = id;
			lg.ludothequeId = member;
			lg.c_minPlayer = game.minPlayer;
			lg.c_maxPlayer = game.maxPlayer;
			lg._game = game;

			links.add(lg);
		}
	}
}
